using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace LowLevelGraphics.Filter
{
    public enum CONV1DMODE
    {
        HORIZONTAL,
        VERTICAL,
        BOTH
    }

    public class Convolution1d : BaseImageFilter
    {
        protected int m_nDiv = 1;
        protected int m_nOffset = 0;

        //if true = vertical, else horizontal
        protected CONV1DMODE m_bVertical = CONV1DMODE.BOTH;

        protected double[] m_aKernel =
            new double[]
            {
                1, 1, 1, 1, 1
            };

        protected double m_nKernelSum = 0;
        /// <summary>
        /// 
        /// </summary>
        public Convolution1d()
        {
            for (int i = 0; i < m_aKernel.Length; i++)
            {
                m_nKernelSum += m_aKernel[i];
            }
        }

        /// <summary>
        /// Clone this
        /// </summary>
        /// <param name="_convolution1d"></param>
        internal Convolution1d(Convolution1d _convolution1d)
        {
            m_aKernel = _convolution1d.m_aKernel;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            int m = 2;
            switch(m_bVertical)
            {
                case CONV1DMODE.VERTICAL:
                    Vertical(_bitmap, m);
                    break;

                case CONV1DMODE.HORIZONTAL:
                    Horizontal(_bitmap, m);
                    break;

                case CONV1DMODE.BOTH:
                    Vertical(_bitmap, m);
                    Horizontal(_bitmap, m);
                    break;
            }
            return _bitmap;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_bitmap"></param>
        protected void Vertical(UnsafeBitmap _bitmap, int m)
        {
            UnsafeBitmap bitmapSource = (UnsafeBitmap)_bitmap.Clone();
            int w = _bitmap.Width;
            int h = _bitmap.Height;
            for (int y = 0; y < h; ++y)
            {
                for (int x = 0; x < w; ++x)
                {
                    uint sum = 0;
                    for (int j = 0; j < m; ++j)
                    {
                        int nX = x;
                        int nY = y - j;
                        if (nY < 0) continue;
                        sum += bitmapSource.GetPixelAsUInt((uint)x, (uint)(nY)) * (uint)m_aKernel[j];
                    }
                    _bitmap.SetPixel(x, y, Color.FromArgb((int)sum));
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="_bitmap"></param>
        protected void Horizontal(UnsafeBitmap _bitmap, int m)
        {
            UnsafeBitmap bitmapSource = (UnsafeBitmap)_bitmap.Clone();
            int h = _bitmap.Height;
            int w = _bitmap.Width;
            for (int y = 0; y < h; ++y)
            {
                for (int x = 0; x < w; ++x)
                {
                    uint sum = 0;
                    for (int i = 0; i < m; ++i)
                    {
                        int nX = x - i;
                        int nY = y;
                        if (nX < 0) continue;
                        sum += bitmapSource.GetPixelAsUInt((uint)(nX), (uint)nY) * (uint)m_aKernel[i];
                    }
                    _bitmap.SetPixel(x, y, Color.FromArgb((int)sum));
                }
            }
        }

        /// <summary>
        /// Clones this instance
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new Convolution1d(this);
        }
    }
}
